import os
import uuid
import tempfile
import shutil
from datetime import datetime, timedelta
from typing import Optional
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
import logging

logger = logging.getLogger(__name__)

class FileService:
    """文件服务"""
    
    def __init__(self, upload_folder: str = None, temp_folder: str = None):
        self.upload_folder = upload_folder or os.path.join(os.path.dirname(__file__), '..', '..', 'uploads')
        self.temp_folder = temp_folder or os.path.join(os.path.dirname(__file__), '..', '..', 'temp')
        
        # 确保目录存在
        os.makedirs(self.upload_folder, exist_ok=True)
        os.makedirs(self.temp_folder, exist_ok=True)
    
    def save_uploaded_file(self, file: FileStorage, file_id: str = None) -> str:
        """
        保存上传的文件
        
        Args:
            file: 上传的文件对象
            file_id: 文件ID，如果不提供则自动生成
            
        Returns:
            保存后的文件路径
        """
        if not file or not file.filename:
            raise ValueError("无效的文件")
        
        # 生成文件ID
        if not file_id:
            file_id = str(uuid.uuid4())
        
        # 安全的文件名
        filename = secure_filename(file.filename)
        if not filename:
            # 如果文件名为空，使用文件ID和扩展名
            ext = self._get_file_extension(file.filename)
            filename = f"{file_id}{ext}"
        
        # 构建保存路径
        file_path = os.path.join(self.upload_folder, f"{file_id}_{filename}")
        
        # 保存文件
        file.save(file_path)
        
        logger.info(f"文件已保存: {file_path}")
        return file_path
    
    def create_temp_file(self, suffix: str = None, prefix: str = None) -> str:
        """
        创建临时文件
        
        Args:
            suffix: 文件后缀
            prefix: 文件前缀
            
        Returns:
            临时文件路径
        """
        fd, temp_path = tempfile.mkstemp(
            suffix=suffix,
            prefix=prefix,
            dir=self.temp_folder
        )
        os.close(fd)
        
        logger.info(f"创建临时文件: {temp_path}")
        return temp_path
    
    def cleanup_old_files(self, max_age_hours: int = 24):
        """
        清理旧文件
        
        Args:
            max_age_hours: 文件最大保存时间（小时）
        """
        cutoff_time = datetime.now() - timedelta(hours=max_age_hours)
        
        # 清理上传文件夹
        self._cleanup_folder(self.upload_folder, cutoff_time)
        
        # 清理临时文件夹
        self._cleanup_folder(self.temp_folder, cutoff_time)
    
    def _cleanup_folder(self, folder_path: str, cutoff_time: datetime):
        """清理指定文件夹中的旧文件"""
        if not os.path.exists(folder_path):
            return
        
        for filename in os.listdir(folder_path):
            file_path = os.path.join(folder_path, filename)
            
            if os.path.isfile(file_path):
                # 获取文件修改时间
                file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
                
                if file_mtime < cutoff_time:
                    try:
                        os.unlink(file_path)
                        logger.info(f"删除旧文件: {file_path}")
                    except Exception as e:
                        logger.error(f"删除文件失败 {file_path}: {str(e)}")
    
    def delete_file(self, file_path: str) -> bool:
        """
        删除文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            是否删除成功
        """
        try:
            if os.path.exists(file_path):
                os.unlink(file_path)
                logger.info(f"文件已删除: {file_path}")
                return True
            return False
        except Exception as e:
            logger.error(f"删除文件失败 {file_path}: {str(e)}")
            return False
    
    def get_file_info(self, file_path: str) -> Optional[dict]:
        """
        获取文件信息
        
        Args:
            file_path: 文件路径
            
        Returns:
            文件信息字典
        """
        if not os.path.exists(file_path):
            return None
        
        stat = os.stat(file_path)
        return {
            'path': file_path,
            'name': os.path.basename(file_path),
            'size': stat.st_size,
            'created': datetime.fromtimestamp(stat.st_ctime),
            'modified': datetime.fromtimestamp(stat.st_mtime),
            'extension': self._get_file_extension(file_path)
        }
    
    def _get_file_extension(self, filename: str) -> str:
        """获取文件扩展名"""
        return os.path.splitext(filename)[1].lower()
    
    def is_allowed_file(self, filename: str, allowed_extensions: set = None) -> bool:
        """
        检查文件是否允许上传
        
        Args:
            filename: 文件名
            allowed_extensions: 允许的扩展名集合
            
        Returns:
            是否允许
        """
        if not allowed_extensions:
            allowed_extensions = {'docx', 'md', 'pdf', 'txt'}
        
        ext = self._get_file_extension(filename).lstrip('.')
        return ext in allowed_extensions 